from db_interface import dbApi
import hashlib # password checking
import json
import datetime
import time
'''
Support application logical model
'''



class baseModel(object):
    '''
    Base model class contains base prototypes database
    abstractions for interacting with database objects. 
    Derived classes can override these methods to create
    custom data providers.
    
    '''



    def __init__(self, dbEngineType='sqlite3'):
        '''
        Setup initial database connection for
        all database interactions
        '''
        #Note: Initial release will only support SQLITE3 embedded database
        # other databases could be added later. Hardcoding method connection here... 
        dbType = dbApi(dbEngineType)
        self.db = dbType.open()
        
    ''' 
    --- START BASE CLASS DEFINITIONS ---1
    Create abstract base methods
    These methods will be available to all derived method. 
    Used as base calls for data operations.
    '''    
    
    
    def getMetaData(self, queryResult):
        '''
        Extract meta data from query
        '''
        metaDataList = [metaData[0] for metaData in queryResult.description]
        return metaDataList
    
    def getDataDict(self, queryResult):
        '''
        Returns result set as a data dictionary
        '''
        columnNames = self.getMetaData(queryResult)
        return [dict(zip(columnNames, dataElement)) for dataElement in queryResult.fetchall()]
        
    def getJsonResults(self, queryResult):
        '''
        package data as json
        '''
        return json.dumps(self.getDataDict(queryResult))
    
    def getUserByUname(self, uname=None):
        '''
        Return single row containing user information
        If data is not found return -> None...
        '''
        sql = "select * from users where uname ='%s'" %(uname)
        result = self.db.query(sql)
        return result.fetchone()
        
    def getUserById(self, uid=None):
        '''
        Return single row containing user information
        If data is not found return -> None...
        '''
        sql = "select * from users where uid ='%s'" %(uid)
        result = self.db.query(sql)
        return result.fetchone()

    def getAllUsers(self):
        '''
        Return all user information
        
        '''
        sql = "select * from users" 
        result = self.db.query(sql)
        return result.fetchall()

    def makeTimeStamp(self):
        '''
        Convert date string into a timestamp
        '''



class userControl(baseModel):
    '''
    Provide user level application methods
    Services:
    1.) Basic user CRUD (CReate, Update, and Delete )
    2.) Login Handler
    3.) User ID Control 
    '''
    
    """ Note: Init called by base class...
    def __init__(self):
        '''
        Setup database interface
        TODO: MOVE TO BASE CLASS LATER!!!!

        '''
        dbType = dbApi('sqlite3')
        self.db = dbType.open()
        
    """    
        
    def checkLogin(self, username, passwd):
        '''
        Get user information from data layer
        Perform checks
        Return results
        '''
        
        # Convert given passwd to hash
        md5pass = hashlib.md5(passwd)
        userData = self.getUserByUname(username)
        print "got this result -> %s" %( userData )
        
        try:
            '''
            Return uid if user information matches
            username && password in database
            Otherwise return None...  
            '''
            print "Testing login Credentials... (%s, %s [%s]) - (%s, %s)" %  (username, passwd, md5pass.hexdigest(), userData['uname'], userData['password'])
            
            if username == userData['uname']: 
                print "[checkLogin] User name is valid"
                if md5pass.hexdigest() == userData['password']:
                    print "[checkLogin] password is valid "
                    '''
                       Return user id to seed in the session cache
                    '''
                    userReturnData = {}
                    userReturnData['ID'] = userData['uid']
                    userReturnData['First'] = userData['namefirst']
                    userReturnData['Last'] = userData['namelast']
                    userReturnData['Email'] = userData['email']
                    userReturnData['Admin'] = userData['isAdmin']
                    
                    return userReturnData
                else:
                    print "Password Failed"
            else:
                print "Login Failed"
                   
        except:
            '''
            Catch all exceptions
            '''
            print "Error processing data!!!!!!!!!!! "
            return None
            
        
    def getUserById(self, ):
        '''
        lookup user information given numerical ID
        return user data
        '''
    
    def getWsAllUsers(self):
        '''
        Return all user information
        
        '''
        sql = "select * from users" 
        result = self.db.query(sql)
        return self.getJsonResults(result)

    


class adminControl(baseModel):
    '''
    Admin interface for program
    '''
    
    def addUser(self, userData):
        '''
        Add a user to the system
        '''
        
        
        
    def delUser(self):
        '''
        Delete user from the system
        '''



class roomControl(baseModel):
    '''
    Interface used to get room information
    '''
    def getRoomList(self):
        '''
        return full listing of rooms
        '''
        sql = "select * from rooms"
        result = self.db.query(sql)
        return result.fetchall()
    
    
    def getWsRoomList(self):
        '''
        return full listing of rooms
        '''
        sql = "select * from rooms"
        result = self.db.query(sql)
        return self.getJsonResults(result)


    def getRoomSizeGreaterThan(self, num):
        '''
        Return rooms large enough for number of guests
        '''
        sql = "select * from rooms where rsize >= %s" %(num)
        result = self.db.query(sql)
        return self.getDataDict(result)

    def addRoom(self, roomData):
        sql = """insert into rooms
        (rname, rdescription, rsize)
        values ('%s','%s',%s)
        """ % (roomData['rname_new'], roomData['rdescription_new'], roomData['rsize_new'])
        print "Inserting SQL -> %s" %(sql)
        self.db.execute(sql)
        
'''
--- CLASS Calendar Control ---
'''
class calendarControl(baseModel):
    '''
    Handles Events
    Got this -> {'eventStrtTimeMer': u'2', 
    'eventStrtTimeHr': u'11', 
    'eventStrt': u'08/29/2011', 
    'eventDurationMin': u'0', 
    'selRoom': u'2', 
    'eventStrtTimeMin': u'30', 
    'selUser': [u'1', u'2', u'3'], 
    'eventDesc': u'Test Event', 
    'eventDurationHr': u'2'}
    '''
    
    
    def addEvent(self, eventData):
        '''
        Add an event to the calendar
        
        
        '''
        dateParts = eventData['eventStrt'].split('/')
        eventHr = int(eventData['eventStrtTimeHr'])
        print "This is date Parts -> %s" %( dateParts)
        if (eventData['eventStrtTimeMer'] == 'p'):
            '''
            
            '''
            eventHr = eventHr + 12
            if (eventHr == 24) :
                eventHr = 0
        
        dateBaseConvert = datetime.datetime(int(dateParts[2]), int(dateParts[0]), int(dateParts[1]), eventHr, int(eventData['eventStrtTimeMin']))
        epochStart = time.mktime(dateBaseConvert.timetuple()).__int__()
        epochEnd = epochStart + ( int(eventData['eventDurationHr']) * 3600 ) +  int(eventData['eventDurationMin']) * 60
        
        sql = """insert into events
        (mdescription,
        mstarttime,
        mendtime,
        mhostid,
        mroomid,
        mstatusid
        )
        values ( '%s', %s, %s, %s, %s, %s );
        """ % (eventData['eventDesc'],
               epochStart, 
               epochEnd, 
               eventData['HOST_ID'], 
               eventData['selRoom'], 
               1) 
        
        print "SQL -> %s" %(sql)
        self.db.execute(sql)
        eventId = self.db.getLastRowId()
        
        
        for uid in eventData['selUser']:
            '''
            add users to the meeting
            Note: In this case asid (Attendee status ID [Are they attending])
            is set to the initial value of 0. This means "invited"
            '''
            sql = """insert into attendees 
            values (%s, %s, 0);
            """ % (eventId, uid)
            print "Inserting SQL -> %s" %(sql)
            self.db.execute(sql)

    def validateEvent(self):
        '''
        Determine if all resources are available
        '''
        
   
     
    def getWsEventList(self, uid):
        '''
        Return a list of events based on the user id 
        that is requesting the schedule
        In general user can only see there own events...
        
        '''
        
        '''
        Get a list of events hosting and attending
        '''
        data = {}
        data['UID'] = uid
        sql = """select 
        '/ws/eventDetail?mid=' ||e.mid as url, 
        e.mstarttime as start, 
        e.mendtime as end, 
        e.mdescription as title,
        0 as allDay
        from 
        events e 
        LEFT JOIN 
        attendees a 
        ON 
        e.mid = a.mid 
        where 
        a.uid = %s or e.mhostid = %s
        group by e.mid;
        """ % (uid, uid)
        print "Getting Events -> %s" % (sql)
        result = self.db.query(sql)
        return self.getJsonResults(result)





